// SampleProject.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <afxtempl.h>
#include <afxmt.h>
#include <map>
#include <list>
#include "Datastore.h"
#include <memory>
#include <iostream>           // std::cout
#include <thread>             // std::thread, std::this_thread::yield
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

template<class Type>
class CListWithLock
{
public:
	POSITION AddTail(Type element)
	{
		m_oLock.Lock();
		POSITION pos = m_oList.AddTail(element);
		m_oLock.Unlock();
		return pos;
	}

	POSITION GetHeadPosition()
	{
		return m_oList.GetHeadPosition();
	}

	Type& GetNext(POSITION& pos)
	{
		return m_oList.GetNext(pos);
	}

	Type GetHead()
	{
		Type result;
		memset(&result, 0, sizeof(result));
		m_oLock.Lock();
		if (0 < m_oList.GetSize())
		{
			result = m_oList.GetHead();
		}
		m_oLock.Unlock();
		return result;
	}

	Type RemoveHead()
	{
		Type result;
		memset(&result, 0, sizeof(result));
		m_oLock.Lock();
		if (0 < m_oList.GetSize())
			result = m_oList.RemoveHead();
		m_oLock.Unlock();
		return result;
	}

	void RemoveAt(POSITION &pos)
	{
		if (pos)
		{
			m_oLock.Lock();
			m_oList.RemoveAt(pos);
			pos = nullptr;
			m_oLock.Unlock();
		}
	}

	void RemoveAll()
	{
		m_oLock.Lock();
		m_oList.RemoveAll();
		m_oLock.Unlock();
	}

	int  GetCount()
	{
		m_oLock.Lock();
		int nCount = m_oList.GetCount();
		m_oLock.Unlock();
		return nCount;
	}

	CListWithLock<Type> & operator=(CListWithLock<Type> & oSrcObject)
	{
		//	m_oLock.Lock();
		m_oList.RemoveAll();
		auto pos = oSrcObject.GetHeadPosition();
		m_oList.AddTail(reinterpret_cast<CList<Type, Type& >*>(pos));
		//		m_oLock.Unlock();
		return *this;
	}

private:
	CList<Type, Type&> m_oList;
	CCriticalSection m_oLock;
};

template<class Type>
class ListWitLock {
	POSITION AddTail(Type element)
	{
		m_oLock.Lock();
		POSITION pos = m_oList.AddTail(element);
		m_oLock.Unlock();
		return pos;
	}

	POSITION GetHeadPosition()
	{
		return m_oList.GetHeadPosition();
	}

	Type& GetNext(POSITION& pos)
	{
		return m_oList.GetNext(pos);
	}

	Type GetHead()
	{
		Type result;
		memset(&result, 0, sizeof(result));
		m_oLock.Lock();
		if (0 < m_oList.GetSize())
		{
			result = m_oList.GetHead();
		}
		m_oLock.Unlock();
		return result;
	}

	Type RemoveHead()
	{
		Type result;
		memset(&result, 0, sizeof(result));
		m_oLock.Lock();
		if (0 < m_oList.GetSize())
			result = m_oList.RemoveHead();
		m_oLock.Unlock();
		return result;
	}

	void RemoveAt(POSITION &pos)
	{
		if (pos)
		{
			m_oLock.Lock();
			m_oList.RemoveAt(pos);
			pos = nullptr;
			m_oLock.Unlock();
		}
	}

	void RemoveAll()
	{
		m_oLock.Lock();
		m_oList.RemoveAll();
		m_oLock.Unlock();
	}

	int  GetCount()
	{
		m_oLock.Lock();
		int nCount = m_oList.GetCount();
		m_oLock.Unlock();
		return nCount;
	}

	CListWithLock<Type> & operator=(CListWithLock<Type> & oSrcObject)
	{
		//	m_oLock.Lock();
		m_oList.RemoveAll();
		auto pos = oSrcObject.GetHeadPosition();
		m_oList.AddTail(reinterpret_cast<CList<Type, Type& >*>(pos));
		//		m_oLock.Unlock();
		return *this;
	}

private:
	std::list<Type> m_oList;
	CCriticalSection m_oLock;
};

std::mutex mtx;
std::condition_variable cv;

int cargo = 0;
bool shipment_available() { return cargo != 0; }

void consume(int n) {
	for (int i = 0; i < n; ++i) {
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck, shipment_available);
		// consume:
		std::cout << cargo << '\n';
		cargo = 0;
	}
}

int main()
{
	std::thread consumer_thread(consume, 100);

	// produce 10 items when needed:
	for (int i = 0; i < 100; ++i) {
		while (shipment_available())
			std::this_thread::yield();
		std::unique_lock<std::mutex> lck(mtx);
		cargo = i + 1;
		cv.notify_one();
	}

	consumer_thread.join();

	CListWithLock<GUID> m_ListObject1, m_ListObject2;

	GUID guid1, guid2, guid3;
	CoCreateGuid(&guid1);
	CoCreateGuid(&guid2);
	CoCreateGuid(&guid3);
	m_ListObject1.AddTail(guid1);
	m_ListObject1.AddTail(guid2);
	m_ListObject1.AddTail(guid3);

	//m_ListObject2 = m_ListObject1;

	char *speed = "8.0";

	auto p_Intptr = speed;
	auto intvalue = std::stof(speed);

	char* pbyte = "0A";

	short shv = atoi("0A");
	short shv2 = 'a';
	//	short sh3 = (short)pbyte;
	auto casint = std::stoi(_T("02C12D"));

	auto ret = pbyte[1] ^ pbyte[1];

	int x = 1;
	int y = 2;
	int z = 3;
	switch (casint)
	{
	case 2:
		y = 3;
	case 3:
		y = 3;
		z = 4;
		break;

	default:
		break;
	}

	Datastore ds;

	auto index = 0;

	//std::shared_ptr<int> pInt(new int());

	Datastore::husObjPtr p_HusDevic(new HUSDevice(index++));

	ds.AddDevice(index, p_HusDevic);

	ds.CreateMore();

	auto p_devPtr = ds.GetDevice(3);

	printf(" cout tttttt :%d", p_devPtr.use_count());

	printf(" cout tttttt :%d", p_devPtr->order);

	return 0;
}